package cn.lifeaid.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.shiro.authz.permission.WildcardPermission;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.lifeaid.db.SysResource;
import cn.lifeaid.db.SysResourceExample;
import cn.lifeaid.utils.Constants;

@Service
public class SysResourceServiceImpl implements SysResourceService {
	@Autowired
	SqlSession sqlSession;

	@Override
	public void createResource(SysResource resource) {
		sqlSession.insert("cn.lifeaid.db.SysResourceMapper.insert", resource);
	}

	@Override
	public void updateResource(SysResource resource) {
		sqlSession.update("cn.lifeaid.db.SysResourceMapper.updateByPrimaryKey",
				resource);
	}

	@Override
	public void deleteResource(Long resourceId) {
		SysResource resource = findOne(resourceId);
		sqlSession.delete("cn.lifeaid.db.SysResourceMapper.deleteByPrimaryKey",
				resourceId);
		// 同时删除以该资源为父级资源的子资源
		SysResourceExample example = new SysResourceExample();
		SysResourceExample.Criteria criteria = example.or();
		criteria.andParentIdsLike(makeSelfAsParentIds(resource) + "%");
		sqlSession.delete("cn.lifeaid.db.SysResourceMapper.deleteByExample",
				example);
	}

	@Override
	public SysResource findOne(Long resourceId) {
		return sqlSession.selectOne(
				"cn.lifeaid.db.SysResourceMapper.selectByPrimaryKey",
				resourceId);
	}

	@Override
	public List<SysResource> findAll() {
		return sqlSession.selectList(
				"cn.lifeaid.db.SysResourceMapper.selectByExample",
				new SysResourceExample());
	}

	@Override
	public Set<String> findPermissions(Set<Long> resourceIds) {
		Set<String> permissions = new HashSet<String>();
		for (Long resourceId : resourceIds) {
			SysResource resource = findOne(resourceId);
			if (resource != null
					&& !StringUtils.isEmpty(resource.getPermission())) {
				permissions.add(resource.getPermission());
			}
		}
		return permissions;
	}

	@Override
	public List<SysResource> findMenus(Set<String> permissions) {
		List<SysResource> allResources = findAll();
		List<SysResource> menus = new ArrayList<SysResource>();
		for (SysResource resource : allResources) {
			if (resource.getParentId() == 0) {
				continue;
			}
			if (resource.getType() != Constants.ResourceType.menu.getInfo()) {
				continue;
			}
			if (!hasPermission(permissions, resource)) {
				continue;
			}
			menus.add(resource);
		}
		return menus;
	}

	private boolean hasPermission(Set<String> permissions, SysResource resource) {
		if (StringUtils.isEmpty(resource.getPermission())) {
			return true;
		}
		for (String permission : permissions) {
			WildcardPermission p1 = new WildcardPermission(permission);
			WildcardPermission p2 = new WildcardPermission(
					resource.getPermission());
			if (p1.implies(p2) || p2.implies(p1)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 将当前资源设置为父级资源
	 * 
	 * @param resource
	 * @return
	 */
	public String makeSelfAsParentIds(SysResource resource) {
		return resource.getParentIds() + resource.getId() + "/";
	}
}
